using System;
using System.Collections.Generic;
using System.Text;
using CodePlex.Resourceful;

namespace CodePlex.SpaceBlock
{
    public class Metadata
    {
        private readonly NameValuePairs _values;
        private readonly Dictionary<string, bool> _readonlies;
        private readonly NameValuePairs _categories;
        private readonly NameValuePairs _descriptions;

        public Metadata()
        {
            _values = new NameValuePairs();
            _readonlies = new Dictionary<string, bool>();
            _categories = new NameValuePairs();
            _descriptions = new NameValuePairs();
        }


        public Metadata(Metadata other) 
        {
            if (other == null)
            {
                _values = new NameValuePairs();
                _readonlies = new Dictionary<string, bool>();
                _categories = new NameValuePairs();
                _descriptions = new NameValuePairs();
            }
            else
            {
                _values = new NameValuePairs(other._values);
                _readonlies = new Dictionary<string, bool>(other._readonlies);
                _categories = new NameValuePairs(other._categories);
                _descriptions = new NameValuePairs(other._descriptions);
            }
        }


        public override string ToString()
        {
            List<string> rt = new List<string>();

            foreach (string key in this.Keys)
            {
                rt.Add(string.Format("{0}={1}", key, this[key]));
            }

            return string.Join(",",rt.ToArray());


        }

        public bool ContainsKey(string key)
        {
            return this.FindKey(key) != null;
        }


        public void Set(string category, string key, string description, string value)
        {
            this.Set(true, category, key, description, value);
        }

        public void Set(bool isReadonly, string category, string key, string description, string value)
        {

            string existingKey = this.FindKey(key);
            if (existingKey != null)
            {
                _values.Remove(existingKey);
                _readonlies.Remove(existingKey);
                _categories.Remove(existingKey);
                _descriptions.Remove(existingKey);
            }

            _values.Add(key, value);
            _readonlies.Add(key, isReadonly);
            _categories.Add(key, category);
            _descriptions.Add(key, description);
        }

        public void Set(string key, string value)
        {
            this.Set(false, "(unknown)", key, "(unknown)", value);
        }

        public void SetIfNew(string key, string value)
        {
            if (!this.ContainsKey(key))
            {
                this.Set(key, value);
            }
        }

        public string this[string key]
        {
            get
            {
                return _values[this.GetKey(key)];
            }
            set
            {
                _values[this.GetKey(key)] = value;
            }
        }


        public IEnumerable<string> Keys
        {
            get
            {
                List<string> rt = new List<string>(_values.Keys);
                rt.Sort();
                return rt;
            }
        }

        public bool GetReadOnly(string key)
        {
            return _readonlies[this.GetKey(key)];
        }

        public string GetCategory(string key)
        {
            return _categories[this.GetKey(key)];
        }

        public string GetDescription(string key)
        {
            return _descriptions[this.GetKey(key)];
        }



        private string GetKey(string key)
        {
            string existingKey = this.FindKey(key);

            if (existingKey == null)
            {
                throw CodePlexException.Format("Key '{0}' not found.", key);
            }

            return existingKey;
        }

        private string FindKey(string key)
        {
            foreach (string existingKey in this.Keys)
            {
                if (existingKey.Equals(key, StringComparison.InvariantCultureIgnoreCase))
                {
                    return existingKey;
                }
            }

            return null;
        }
    }
}
